﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace engine
{
    public class Engine
    {
        public List<Fact> fristfacts
        {
            get;
            set;
        }
        public List<Rule> rules
        {
            get;
            set;
        }
        IEngineImportFact listener = null;
        public Engine()
        {
            fristfacts = new List<Fact>();
            rules = new List<Rule>();
        }

        
        
        public void setOnEngineImportFact(IEngineImportFact _listener)
        {
            this.listener = _listener;
        }
        /*
         * Ham tim kiem cac luat co menh de la su kien co truoc
         * @return tap luat duoi dang ngan xep
         */
        private Stack<Rule> findRuleshasGoal(Fact goal)
        {
            Stack<Rule> _return = new Stack<Rule>();
            if (rules == null || rules.Count == 0)
                return null;

            foreach (Rule rule in rules)
            {
                if (rule.rightFact.Key.CompareTo(goal.Key) == 0)
                {
                    _return.Push(rule);
                }
            }
            return _return;
        }
        /*
         * Thuat toan suy dien lui
         */
        public Fact backTracking(Fact goal)
        {
            Stack<Rule> needRules = findRuleshasGoal(goal);
            if (needRules ==null || needRules.Count == 0)
            {
                if (listener == null) 
                    return null;
                return listener.getFactbyUser(goal);
            }
            else
            {
                while (needRules.Count != 0)
                {
                    Rule temp = needRules.Pop();
                    if (checkCondition(temp))
                    {
                        goal.value = temp.rightValue;
                        fristfacts.Add(goal);
                        return goal;
                    }
                }
            }
            return null;
        }
        /*
         * Ham duyet dieu kien luan if-then
         * @return true khi dieu kien dung
         * @return fasle khi dieu kien sai
         */
        private Boolean checkCondition(Rule rule)
        {
            if(rule == null || rule.Condition.Count ==0)
                return false;
            Boolean _return = true;
            foreach (Equation equation in rule.Condition)
            {
                foreach (Fact fact in fristfacts)
                {
                    if (fact.Key.CompareTo(equation.leftFact.Key) == 0){
                        if (!fact.value.CheckCondition(equation.Operator, equation.leftValue))
                            return false;
                        break;
                    }
                }
                Fact temp = backTracking(equation.leftFact);
                if(temp == null)
                        return false;
                if (!temp.value.CheckCondition(equation.Operator, equation.leftValue))
                        return false;
            }
            return _return;
        }
        /*
         * Ham kiem tra dieu kien luan if-then
         * @return true khi dieu kien dung
         * @return fasle khi dieu kien sai
         */
        private Boolean isCondition(Fact fact, String opertor, SampleObject value)
        {
            return false;
        }
    }
}
